﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using KaiXin.BLL.Interface;
using KaiXin.DTO.Tycoon;
using HtmlAgilityPack;
using KaiXin.DAL.XML;

namespace KaiXin.BLL.Tycoon
{
    public class KXTycoon : Robot, IKXTycoon
    {
       
        #region field
        
        private Persistence<Goods> _dal = PersistenceFactory.GoodsDAL;
        
        #endregion

        #region private

        private List<GoodsClass> GetAllClasses()
        {
            List<GoodsClass> list = new List<GoodsClass>();
            GoodsClass[] gc = {
                                  new GoodsClass() { Name = "街头小贩", StartURL = "http://www.kaixin001.com/!rich/market.php?cateid=1", ID = 1 },
                                  new GoodsClass() { Name = "商　　业", StartURL = "http://www.kaixin001.com/!rich/market.php?cateid=2", ID = 2 },
                                  new GoodsClass() { Name = "休闲娱乐", StartURL = "http://www.kaixin001.com/!rich/market.php?cateid=4", ID = 4 },
                                  new GoodsClass() { Name = "交　　通", StartURL = "http://www.kaixin001.com/!rich/market.php?cateid=6", ID = 6 },
                                  new GoodsClass() { Name = "地产置业", StartURL = "http://www.kaixin001.com/!rich/market.php?cateid=7", ID = 7 },
                                  new GoodsClass() { Name = "　奢侈品", StartURL = "http://www.kaixin001.com/!rich/market.php?cateid=8", ID = 8 },
                                  new GoodsClass() { Name = "科技产品", StartURL = "http://www.kaixin001.com/!rich/market.php?cateid=9", ID = 9 },
                                  new GoodsClass() { Name = "军事武器", StartURL = "http://www.kaixin001.com/!rich/market.php?cateid=10", ID = 10 }
                              };
            list.AddRange(gc);
            return list;
        }

        private List<Goods> GetGoodsByHTML(HtmlDocument html, GoodsClass type)
        {

            List<Goods> list = new List<Goods>();
            HtmlNodeCollection nc = html.DocumentNode.SelectNodes("//ul");
            if (nc != null)
            {
                foreach (var item in nc)
                {
                    Goods goods = new Goods();
                    goods.Class = type;
                    goods.Name = item.SelectSingleNode("./li[2]/b").InnerText;
                    if (item.SelectSingleNode(".//a") == null)
                    {
                        continue;
                    }
                    string href = item.SelectSingleNode(".//a").Attributes["href"].Value;
                    int s = href.IndexOf("(") + 1;
                    int e = href.IndexOf(",");
                    goods.ID = href.Substring(s, e - s);

                    s = href.IndexOf("'") + 1;
                    e = href.IndexOf("'", s);
                    goods.CurrentPrice = long.Parse(href.Substring(s, e - s));

                    list.Add(goods);
                }
            }

            return list;
        }

        private List<Goods> GetGoodsByClass(GoodsClass type)
        {
            HtmlDocument doc = AccessPage(type.StartURL);
            int pageCount = Common.GetPageCount(doc);
            List<Goods> list = GetGoodsByHTML(doc, type);
            for (int i = 1; i < pageCount; i++)
            {
                doc = AccessPage(type.StartURL + "&start=" + i * 20);
                list.AddRange(GetGoodsByHTML(doc, type));
            }
            return list;
        }
        /// <summary>
        /// 检测物品价格浮动，并对浮动的价格做持久化修改
        /// </summary>
        /// <param name="list"></param>
        /// <returns></returns>
        private void CheckGoods(List<Goods> list)
        {
            foreach (var goods in list)
            {
                if (!_dal.IsExist(goods))
                {
                    _dal.AddItem(goods);
                }
                _dal.InitItem(goods);
                if (goods.MaxPrice < goods.CurrentPrice)
                {
                    goods.MaxPrice = goods.CurrentPrice;
                    _dal.FixItem(goods);//修改最大值
                    Log.WriteLog(string.Format("{0}最大值修改为{1}    【{2}】", goods.Name, goods.MaxPrice, DateTime.Now));
                }
                else if (goods.MinPrice > goods.CurrentPrice)
                {
                    goods.MinPrice = goods.CurrentPrice;
                    _dal.FixItem(goods);//修改最小值
                    Log.WriteLog(string.Format("{0}最小值修改为{1}    【{2}】", goods.Name, goods.MinPrice, DateTime.Now));
                }
                else if (goods.LastPrice != goods.CurrentPrice)
                {
                    goods.LastPrice = goods.CurrentPrice;//修改上次价格
                    _dal.FixItem(goods);//修改价格
                    if (PriceChangeEvent != null)
                    {
                        PriceChangeEvent(goods);
                    }
                }
            }

        }

        #endregion

        #region IKXTycoon 成员

        public List<Goods> GetGoods(Func<GoodsClass, bool> func)
        {
            List<Goods> list = new List<Goods>();
            foreach (var item in GetAllClasses())
            {
                if (func==null || func(item))
                {
                    list.AddRange(GetGoodsByClass(item));
                }
            }
            CheckGoods(list);
            PersistenceFactory.GoodsDAL.Save();//将最大最小值的修改保存
            return list;
        }

        public List<Goods> GetGoods()
        {
            return GetGoods(null);
        }

        public List<Goods> GetTOP10(Func<Goods, bool> func)
        {
            List<Goods> list = GetGoods().OrderByDescending(g => g.Prec).ToList();//以百分比排序
            List<Goods> result = new List<Goods>();
            foreach (var item in list)
            {
                if (func(item))
                {
                    result.Add(item);
                    if (result.Count == 10)
                        break;
                }
            }
            return result;
        }
        public event PriceChange PriceChangeEvent;

        #endregion
    }
}
